package org.aj.common.web.file.web;


import org.aj.base.annotation.IgnoreInputLog;
import org.aj.base.exception.BusException;
import org.aj.base.web.response.ResponseResult;
import org.aj.common.web.file.bean.FileMetadata;
import org.aj.common.web.file.bean.FileRetWrap;
import org.aj.common.web.file.bean.FileVo;
import org.aj.common.web.file.service.FileUploadBaseServiceImpl;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * description 文件上传通用性接口
 * @author aj
 * date  2022/1/2 22:46
 */
@ResponseBody
public class FileUploadBaseController {

    private static final Logger log = LoggerFactory.getLogger(FileUploadBaseController.class);
    private static final int RELATIVE_PATH_MAX_LENGTH = 200;

    private final FileUploadBaseServiceImpl fileUploadService;

    public FileUploadBaseController(FileUploadBaseServiceImpl fileUploadService) {
        this.fileUploadService = fileUploadService;
    }



    /**
     * description 上传照片返回 相对路径和绝对路径
     * @author aj
     * date  2022/1/3 17:27
     * @param fileVo
     * @return com.iotimc.yimi.base.bean.reqrsp.ResponseResult
     */
    @IgnoreInputLog
    @PostMapping("${aj.web.file.base64UploadFile.uri:/file/uploadFile}")
    public ResponseResult uploadFile(@RequestBody @Valid FileVo fileVo) throws Exception {
        long start = System.currentTimeMillis();
        if (StringUtils.isNotBlank(fileVo.getBeforeRelativePath()) && fileVo.getBeforeRelativePath().length() > RELATIVE_PATH_MAX_LENGTH) {
            return ResponseResult.error("beforeRelativePath 超过最大值"+RELATIVE_PATH_MAX_LENGTH);
        }
        FileRetWrap urlJson = fileUploadService.uploadFile(fileVo);

        ResponseResult<FileRetWrap> success = ResponseResult.success("success", urlJson);
        String timeDiff = String.format("%.3f", (System.currentTimeMillis() - start) * 1.0 / 1000);
        log.info("base64文件上传入口,请求参数{{}},返回结果{{}},请求耗时{{}}",fileVo.printButOnlyBase64Length(),urlJson.toString(),timeDiff);
        return success;
    }

    /**
     * 在上传文件过程中出现异常
     */
    public static final Integer UPLOADING_ERROR=602;

    /**
     * description  传统形式的上传文件
     * @param request
     * @param type 上传类型 对应的是保存地址
     * @param needKeepOriginalName 是否需要保留原来的文件名称
     * @param beforeRelativePath      上一次上传文件返回的相对路径 若传了则用这个路径直接覆盖掉之前的
     *                                会按照顺序进行覆盖。已上传图片集合的长度为准 超出或者少了的则不会覆盖
     * @return: com.iotimc.common.reqrsp.ResponseResult
     * @author: jcj
     * date : 2020/12/31 16:47
     */
    @RequestMapping("${aj.web.file.uploadFileOfTradition.uri:/file/uploadFileOfTradition}")
    public ResponseResult uploadFileOfCommon(@RequestParam String type
                                             ,@RequestParam(required = false) String[] beforeRelativePath
                                             ,@RequestParam(required = false,defaultValue = "false") Boolean needKeepOriginalName
                                             ,HttpServletRequest request){

        if( ! (request instanceof MultipartHttpServletRequest)){

            return ResponseResult.error("此接口目前只处理上传文件");
        }
        //获取到相对根路径
        String relativeRootPath =  type.trim();


        //转换成用于提取文件的请求
        MultipartHttpServletRequest multipartReq = (MultipartHttpServletRequest) request;

        MultiValueMap<String, MultipartFile> multiFileMap = multipartReq.getMultiFileMap();


        if(null == multiFileMap || multiFileMap.isEmpty()){
            return ResponseResult.error("未接收到任何文件");
        }
        if (multiFileMap.size() > 10) {
            return ResponseResult.error("目前及支持批量上传10");
        }

        if(!ArrayUtils.isEmpty(beforeRelativePath)){
            for (String s : beforeRelativePath) {
                if(s.length() > RELATIVE_PATH_MAX_LENGTH){
                    return ResponseResult.error("beforeRelativePath 超过最大值"+RELATIVE_PATH_MAX_LENGTH);
                }
            }
        }

        //记录保存的路径
        List<ResponseResult<FileRetWrap>> resList = new ArrayList<>();
        int index=0;
        for (Map.Entry<String, List<MultipartFile>> listEntry : multiFileMap.entrySet()) {


            //得到文件对象
            List<MultipartFile> multipartFiles = listEntry.getValue();

            //得到key 即file对象对应的key
            String key = listEntry.getKey();

            //遍历文件对象进行保存操作

            for (MultipartFile multipartFile : multipartFiles) {
                index++;
                try {
                    byte[] bytes = multipartFile.getBytes();

                    FileMetadata fileMetadata = new FileMetadata()
                            .setContentType(multipartFile.getContentType())
                            .setSubFolderPath(relativeRootPath)
                            .setNeedKeepOriginalName(needKeepOriginalName)
                            .setBytes(bytes)
                            .setFileName(multipartFile.getOriginalFilename());

                    if(!ArrayUtils.isEmpty(beforeRelativePath)
                            && index < beforeRelativePath.length
                            &&  StringUtils.isNotBlank(beforeRelativePath[index]) ){
                        fileMetadata.setBeforeRelativePath(beforeRelativePath[index]);
                    }

                    FileRetWrap build = fileUploadService.distributeUpload(fileMetadata);
                    build.setKey(key);
                    resList.add(ResponseResult.success("success",build));
                } catch (Exception e) {
                    if(e instanceof BusException){
                        resList.add(ResponseResult.getErrorResult(e.getMessage(),((BusException) e).codeConvertToInteger()));
                    }else{
                        log.error("上传文件" + multipartFile.getOriginalFilename() + "到分布式文件系统异常：", e);
                        resList.add(ResponseResult.getErrorResult("网络异常，上传失败",UPLOADING_ERROR));
                    }

                }

            }

        }
        return ResponseResult.getSuccessResultPackageList("success",resList);
    }



    /**
     * description  传统形式的上传文件
     * @param multipartFile
     * @param type 上传类型 对应的是保存地址
     * @param needKeepOriginalName 是否需要保留原来的文件名称
     * @param beforeRelativePath 上一次上传文件返回的相对路径 若传了则用这个路径直接覆盖掉之前的
     * @return: com.iotimc.common.reqrsp.ResponseResult
     * @author: jcj
     * date : 2020/12/31 16:47
     */
    @RequestMapping("${aj.web.file.uploadFileOfTraditionSingle.uri:/file/uploadFileOfTraditionSingle}")
    public ResponseResult uploadFileOfTraditionSingle(@RequestParam String type
            ,@RequestParam(required = false) String beforeRelativePath
            ,@RequestParam(required = false,defaultValue = "false") Boolean needKeepOriginalName
            ,@RequestParam MultipartFile multipartFile) throws Exception {


        //获取到相对根路径
        String relativeRootPath =  type.trim();
        if(StringUtils.isBlank(relativeRootPath)){
            return ResponseResult.error("请指定子路径");
        }

        if(null == multipartFile || multipartFile.isEmpty()){
            return ResponseResult.error("未接收到任何文件");
        }

        if(StringUtils.isNotBlank(beforeRelativePath) && beforeRelativePath.length() > RELATIVE_PATH_MAX_LENGTH){
            return ResponseResult.error("beforeRelativePath 超过最大值"+RELATIVE_PATH_MAX_LENGTH);
        }

        //封装文件元对象
        FileMetadata fileMetadata = new FileMetadata()
                .setContentType(multipartFile.getContentType())
                .setSubFolderPath(relativeRootPath)
                .setNeedKeepOriginalName(needKeepOriginalName)
                .setBytes(multipartFile.getBytes())
                .setBeforeRelativePath(beforeRelativePath)
                .setFileName(multipartFile.getOriginalFilename());
        //上传文件
        FileRetWrap build = fileUploadService.distributeUpload(fileMetadata);

        return ResponseResult.success("success",build);
    }



    @RequestMapping("${aj.web.file.delFiles.uri:/file/delFiles}")
    public ResponseResult delFiles(@RequestParam Set<String> destFilePathArr) throws Exception {
        if(destFilePathArr.isEmpty())
            return ResponseResult.error("请传入要删除文件的相对路径");
        if (destFilePathArr.size() > 10) {
            return ResponseResult.error("目前及支持批量删除10");
        }
        return fileUploadService.delFiles(destFilePathArr);
    }


}
